#include "conexmain.h"
#include <QtGui>
#include <QString>
#include <map>
#include <string>
#include "control/VocabularyControl.h"
#include "control/VocabularyXmlControl.h"
#include "model/Term.h"

ConexMain::ConexMain(QWidget *parent, Qt::WFlags flags)
	: QMainWindow(parent, flags), 
	_voc(NULL), 
	_model(NULL),
	_modifymodel(NULL),
	_namespacemodel(NULL),
	_authormodel(NULL),
	_hypernymmodel(NULL),
	_classifiermodel(NULL),
	_antonymmodel(NULL),
	_similarmodel(NULL),
	_synonymmodel(NULL),
	_currentTerm(NULL),
	_pagesize(30),
	_findDialog(this),
	_vocControl(conex::VocabularyControl::XML_SAX2),
	_termControl(0)
{
	ui.setupUi(this);
	_pagesize = ui.pageSizeComboBox->currentText().toInt();	
	//
	ui.actionSave_Term->setEnabled(false);
	conex::VocabularyXmlControl _vocControl(conex::VocabularyControl::XML_SAX2);
	//connect(ui.actionOpenVocFile, SIGAINL(trigged()), 
	connect(ui.actionOpenVocFile, SIGNAL(triggered()), this, SLOT(OpenVoc()));
	connect(ui.actionOpenEn, SIGNAL(triggered()), this, SLOT(OpenEn()));
	connect(ui.actionOpenChs, SIGNAL(triggered()), this, SLOT(OpenChs()));
	connect(ui.actionSave_Voc, SIGNAL(triggered()), this, SLOT(SaveVoc()));
	connect(ui.actionSave_As, SIGNAL(triggered()), this, SLOT(SaveAs()));
	//term maangement
	connect(ui.tableView, SIGNAL(activated (const QModelIndex &)), this, SLOT(ViewClicked(const QModelIndex&)));
	connect(ui.actionAdd_Term, SIGNAL(triggered()), this, SLOT(NewTerm()));
	connect(ui.actionSave_Term, SIGNAL(triggered()), this, SLOT(SaveTerm()));
	connect(ui.actionRemove_Term, SIGNAL(triggered()), this, SLOT(RemoveTerm()));
	connect(ui.addTermButton, SIGNAL(clicked()), this, SLOT(NewTerm()));
	connect(ui.saveTermButton, SIGNAL(clicked()), this, SLOT(SaveTerm()));
	connect(ui.removeTermButton, SIGNAL(clicked()), this, SLOT(RemoveTerm()));
	//find terms
	connect(ui.findButton, SIGNAL(clicked()), this, SLOT(FindTerms()));
	connect(ui.findLineEdit, SIGNAL(returnPressed ()), this, SLOT(FindTerms()));
	//bind pageing
	connect(ui.firstPageButton, SIGNAL(clicked()), this, SLOT(FirstPage()));
	connect(ui.nextButton, SIGNAL(clicked()), this, SLOT(NextPage()));
	connect(ui.previewButton, SIGNAL(clicked()), this, SLOT(PreviewPage()));
	connect(ui.lastButton, SIGNAL(clicked()), this, SLOT(LastPage()));
	connect(ui.pageComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(GetPage(int)));
	connect(ui.pageSizeComboBox, SIGNAL(currentIndexChanged(const QString & )), this, SLOT(SetPagesize(const QString & )));
	//context management
	connect(ui.addSynonymsButton, SIGNAL(clicked()), this, SLOT(AddSynonyms()));
	connect(ui.addNamespacesButton, SIGNAL(clicked()), this, SLOT(AddNamespace()));
	connect(ui.addAuthorButton, SIGNAL(clicked()), this, SLOT(AddAuthor()));
	connect(ui.addHypernymButton, SIGNAL(clicked()), this, SLOT(AddHypernyms()));
	connect(ui.addClassifierButton, SIGNAL(clicked()), this, SLOT(AddClassifier()));
	connect(ui.addAntonymButton, SIGNAL(clicked()), this, SLOT(AddAntonym()));
	connect(ui.addSimilarButton, SIGNAL(clicked()), this, SLOT(AddSimilar()));
	ui.pageComboBox->setInsertPolicy(QComboBox::InsertAtBottom);
	_findDialog.hide();
	ShowContext(true);
	//OpenVocFromFile();
}

ConexMain::~ConexMain()
{
	SAFE_DELETE(_model);
	SAFE_DELETE(_modifymodel);
	SAFE_DELETE(_namespacemodel);
	SAFE_DELETE(_authormodel);
	SAFE_DELETE(_hypernymmodel);
	SAFE_DELETE(_classifiermodel);
	SAFE_DELETE(_antonymmodel);
	SAFE_DELETE(_similarmodel);
	SAFE_DELETE(_synonymmodel);	
}

void ConexMain::OpenVoc() {
	if (MaybeSave()) {
		QString filename =	QFileDialog::getOpenFileName(this);
		OpenVocFromFile(filename);
	}

}

void ConexMain::OpenVocFromFile(QString filename) {
	ui.statusBar->showMessage(tr("Loading Vocabulary From XML!"));
	//connect(ui.
	if(_vocControl.GetFile() != filename.toAscii().constData()) {			
		_vocControl.SetFile(filename.toAscii().constData());
		if ( _voc != 0 ) {
			_voc->ClearTerms();
			delete _voc;
			_voc = 0;
		}
		_voc = new conex::Vocabulary();
		_vocControl.Load(*_voc);
		if(_termControl != 0) {
			delete _termControl;
			_termControl = 0;
		}
		_termControl = new conex::TermControl(_voc);
		_findDialog.SetVocabularyAndTermControl(_voc, _termControl);
	}	
	FindTerms();
	QString title = tr("Vocabulary Management for Conex - ") + filename;
	setWindowTitle(title);
	ui.statusBar->showMessage(tr("Loaded Vocabulary From XML!"));
}

void ConexMain::OpenEn() {
	if ( MaybeSave()) {
		QString filename = QApplication::applicationDirPath() + "/data/Vocabulary_en_1.0.0.xml";
		OpenVocFromFile(filename);
	}
}

void ConexMain::OpenChs() {
	if ( MaybeSave()) {
		QString filename = QApplication::applicationDirPath() + "/data/Vocabulary_zh_1.0.0.xml";
		OpenVocFromFile(filename);
	}
}

bool ConexMain::MaybeSave() {
	return true;
}

void ConexMain::SaveVoc() {		
	if(MaybeSave()) {
		if(_voc) {		
			string message = "Saving " + _vocControl.GetFile();
			ui.statusBar->showMessage(tr(message.c_str()));
			_vocControl.Save(*_voc);
			message = "Saved " + _vocControl.GetFile();
			ui.statusBar->showMessage(tr(message.c_str()));
		}
	}

}

void ConexMain::SaveAs() {
	if(MaybeSave()) {
		QString filename =	QFileDialog::getSaveFileName(this);		
		if(_voc) {			
			_vocControl.SetFile(filename.toAscii().constData());
			string message = "Saving " + _vocControl.GetFile();
			ui.statusBar->showMessage(tr(message.c_str()));
			_vocControl.Save(*_voc);
			message = "Saved " + _vocControl.GetFile();
			ui.statusBar->showMessage(tr(message.c_str()));
			QString title = tr("Vocabulary Management for CONEX - ") + filename;
			setWindowTitle(title);
		}		
	}
}

void ConexMain::ViewClicked(const QModelIndex& index) {
	int row = index.row();
	string id(ui.tableView->model()->data(ui.tableView->model()->index(row, 3)).toByteArray().constData());
	_currentTerm = _voc->GetTermByIid(id);
	if(_currentTerm) {
		DisplayTerm(_currentTerm);		
		ShowContext(true);
		ui.termTab->setCurrentIndex(0);
	}
}

void ConexMain::DisplayTerm(conex::Term* term) {
	QString iid(term->id()->iid().c_str());
	QString word = stdWToQString(term->id()->word());
	QString pos(term->pos().c_str());
	QString ponetines(term->phonetic().c_str());
	QString textExp = stdWToQString(term->text());
	QString iidExp(term->structure()->iids().c_str());
	ui.iidValueLabel->setText(iid);
	ui.textValueEdit->setText(word);
	ui.posValueEdit->setText(pos);
	ui.ponetenicsValueEdit->setText(ponetines);
	ui.textExplaValueText->setText(textExp);
	ui.iidExplaValueText->setText(iidExp);
	ui.actionSave_Term->setEnabled(true);
	//ui.textValueEdit-->
}

void ConexMain::DisplayClear() {
	ui.iidValueLabel->setText(tr(""));
	ui.textValueEdit->setText(tr(""));
	ui.posValueEdit->setText(tr(""));
	ui.ponetenicsValueEdit->setText(tr(""));
	ui.textExplaValueText->setText(tr(""));
	ui.iidExplaValueText->setText(tr(""));
	//ui.textValueEdit-->
}

void ConexMain::LoadTerm(conex::Term* term) {	
	if(_currentTerm && _termControl) {
		QString text = ui.textValueEdit->text();
		_termControl->SetWord(qToStdWString( text), _currentTerm);
		QString pos = ui.posValueEdit->text();
		_termControl->SetPos(pos.toAscii().constData(), _currentTerm);
		QString ponetenis = ui.ponetenicsValueEdit->text();
		_termControl->SetPonetenics(ponetenis.toAscii().constData(), _currentTerm);
		QString textExp = ui.textExplaValueText->toPlainText();
		_termControl->SetTextExplanation(qToStdWString(textExp), _currentTerm);
		QString iidExp = ui.iidExplaValueText->toPlainText();
		_termControl->SetIidExplanation(iidExp.toAscii().constData(), _currentTerm);
		ui.statusBar->showMessage(tr("Saved Term : ") + text + tr(" Iid: ") + ui.iidValueLabel->text() );
	}
	//ui.textValueEdit-->
}

void ConexMain::SaveTerm() {
	if(_currentTerm && _termControl ) {
		//it is important to remove term index before load the term
		_termControl->RemoveTermIndex(_currentTerm);
		LoadTerm(_currentTerm);
		string pos = ui.posValueEdit->text().toAscii().constData();
		_termControl->SaveTerm(_currentTerm, pos, "");
		//_model.LoadData(_voc);
		ui.termViewTab->setCurrentIndex(1);
		ui.actionSave_Term->setDisabled(true);
		FindTerms();
		FindModifiesTerms();
	}
}

void ConexMain::RemoveTerm() {
	if(_currentTerm && _termControl) {
		QString message = tr("Removed Current Term !");
		_termControl->RemoveTerm(_currentTerm);
		DisplayClear();
		ui.statusBar->showMessage(message );
		ui.actionSave_Term->setDisabled(true);
		FindTerms();
		FindModifiesTerms();
	}	
}

void ConexMain::NewTerm() {
	if(_voc && _termControl) {
		DisplayClear(); 
		ui.termViewTab->setCurrentIndex(1);
		ui.textValueEdit->setFocus();
		_currentTerm = _termControl->CreateTerm();
		QString iid(_currentTerm->id()->iid().c_str());
		ui.iidValueLabel->setText(iid);
		ui.actionSave_Term->setEnabled(true);
		ui.statusBar->showMessage(tr("Please fill the data in the term!!!!") );	 
	}
}

void ConexMain::FindTerms() {
	if(_voc == 0 || _termControl == 0)
		return;
	QString text = ui.findLineEdit->text();
	ui.statusBar->showMessage(tr("Finding terms from the prefix of ") + text);
	vector<conex::Term*> terms;
	if(!text.isEmpty()) {		
		wstring prefix(qToStdWString( text));
		_termControl->PrefixSearch(prefix, terms);		

	}else {
		_voc->GetTopkTerms(0, terms);
	}
	SAFE_DELETE(_model);
	_model = new conex::VocabularyTableModel(this);	
	int pagecount = _model->LoadData(terms);	
	SetPageCount(pagecount);
	ui.tableView->setModel(_model);
	ui.tableView->resizeColumnsToContents();
	ui.findLineEdit->setFocus();
	QModelIndex index = _model->index(0,0);
	ui.tableView->setCurrentIndex(index);
	ui.statusBar->showMessage(tr("Finded terms from the prefix of ") + text);
}

void ConexMain::FindModifiesTerms() {
	vector<conex::Term*> terms;
	_termControl->GetModifyTerms(terms);
	SAFE_DELETE(_modifymodel);
	_modifymodel = new conex::VocabularyTableModel(this);
	_modifymodel->LoadData(terms);
	ui.modifyTableView->setModel(_modifymodel);
	ui.modifyTableView->resizeColumnsToContents();	
	QModelIndex index = _modifymodel->index(0,0);
	ui.modifyTableView->setCurrentIndex(index);
}

//term paging
void ConexMain::FirstPage() {
	if(_model) {
		_model->FirstPage();
		ui.tableView->setModel(_model);
		ui.tableView->resizeColumnsToContents();
		ChangePageIndex();
	}
}
void ConexMain::NextPage() {
	if(_model) {
		_model->NextPage();
		ui.tableView->setModel(_model);
		ui.tableView->resizeColumnsToContents();
		ChangePageIndex();
	}
}
void ConexMain::PreviewPage() {
	if(_model) {
		_model->PreviewPage();
		ui.tableView->setModel(_model);
		ui.tableView->resizeColumnsToContents();
		ChangePageIndex();
	}
}
void ConexMain::LastPage() {
	if(_model) {
		_model->LastPage();
		ui.tableView->setModel(_model);
		ui.tableView->resizeColumnsToContents();
		ChangePageIndex();
	}
}
void ConexMain::SetPageCount(int pagecount) {
	QStringList items;
	for(int i = 0; i < pagecount; i++) {
		int page = i+1;
		QString page_str = QString::number(page, 10);
		items << page_str;
	}
	ui.pageComboBox->setInsertPolicy(QComboBox::InsertAtBottom);
	ui.pageComboBox->addItems(items);
	ui.pageComboBox->setCurrentIndex(0);
}
void ConexMain::GetPage(int index) {
	if(_model) {
		int page = index + 1;
		_model->GetPage(page);
		ui.tableView->setModel(_model);
		ui.tableView->resizeColumnsToContents();
	}
}
void ConexMain::SetPagesize(const QString & text) {
	if(_model) {
		_pagesize = text.toInt();
		int pagecount = _model->SetPageSize(_pagesize);
		SetPageCount(pagecount);
		ui.tableView->setModel(_model);
		ui.tableView->resizeColumnsToContents();
	}
}

void ConexMain::ChangePageIndex() {
	if(_model) {
		int currentpage = _model->GetCurrentPage();
		ui.pageComboBox->setCurrentIndex(currentpage -1);
	}
}

void ConexMain::AddSynonyms() {
	if(_currentTerm) {
		if( _findDialog.exec() == QDialog::Accepted) {
			conex::Term* relatedTerm = _findDialog.GetSelectedTerm();
			if(_currentTerm && relatedTerm) {
				_currentTerm->context()->AddRelation(conex::SYNONYM, relatedTerm);
				wstring message = L"Term: " + _currentTerm->id()->word() + L" Added Synonym of Term: " + relatedTerm->id()->word();
				ui.statusBar->showMessage(stdWToQString(message.c_str()));
				ShowContext(true);
			}
		}
	}
}

//context management
void ConexMain::AddNamespace() {
	if(_voc) {
		if( _findDialog.exec() == QDialog::Accepted) {
			conex::Term* relatedTerm = _findDialog.GetSelectedTerm();
			if(_voc && relatedTerm) {
				//_voc->GetVocabularyContext()->AddNamespace()->RelatedTo(relatedTerm);
				wstring message = L"Vocabulary:  Added Namespace of Term: " + relatedTerm->id()->word();
				ui.statusBar->showMessage(stdWToQString(message.c_str()));
				ShowContext(false);
			}
		}
	}
}
void ConexMain::AddAuthor() {
	if(_voc) {
		if( _findDialog.exec() == QDialog::Accepted) {
			conex::Term* relatedTerm = _findDialog.GetSelectedTerm();
			if(_voc && relatedTerm) {
				//_voc->GetVocabularyContext()->AddAuthor()->RelatedTo(relatedTerm);
				wstring message = L"Vocabulary: Added Author of Term: " + relatedTerm->id()->word();
				ui.statusBar->showMessage(stdWToQString(message.c_str()));
				ShowContext(false);
			}
		}
	}
}
void ConexMain::AddHypernyms() {
	if(_currentTerm) {
		if( _findDialog.exec() == QDialog::Accepted) {
			conex::Term* relatedTerm = _findDialog.GetSelectedTerm();
			if(_currentTerm && relatedTerm) {
				_currentTerm->context()->AddRelation(conex::HYPERNYM, relatedTerm);
				wstring message = L"Term: " + _currentTerm->id()->word() + L" Added Hypernym of Term: " + relatedTerm->id()->word();
				ui.statusBar->showMessage(stdWToQString(message.c_str()));
				ShowContext(true);
			}
		}
	}
}
void ConexMain::AddClassifier() {
	if(_currentTerm) {
		if( _findDialog.exec() == QDialog::Accepted) {
			conex::Term* relatedTerm = _findDialog.GetSelectedTerm();
			if(_currentTerm && relatedTerm) {
				_currentTerm->context()->AddRelation(conex::CATEGORY, relatedTerm);
				wstring message = L"Term: " + _currentTerm->id()->word() + L" Added Classifier of Term: " + relatedTerm->id()->word();
				ui.statusBar->showMessage(stdWToQString(message.c_str()));
				ShowContext(true);
			}
		}
	}
}
void ConexMain::AddAntonym() {
	if(_currentTerm) {
		if( _findDialog.exec() == QDialog::Accepted) {
			conex::Term* relatedTerm = _findDialog.GetSelectedTerm();
			if(_currentTerm && relatedTerm) {
				_currentTerm->context()->AddRelation(conex::ANTONYM, relatedTerm);
				wstring message = L"Term: " + _currentTerm->id()->word() + L" Added Antonym of Term: " + relatedTerm->id()->word();
				ui.statusBar->showMessage(stdWToQString(message.c_str()));
				ShowContext(true);
			}
		}
	}
}
void ConexMain::AddSimilar() {
	if(_currentTerm) {
		if( _findDialog.exec() == QDialog::Accepted) {
			conex::Term* relatedTerm = _findDialog.GetSelectedTerm();
			if(_currentTerm && relatedTerm) {
				_currentTerm->context()->AddRelation(conex::SIMINYM, relatedTerm);
				wstring message = L"Term: " + _currentTerm->id()->word() + L" Added Similar of Term: " + relatedTerm->id()->word();
				ui.statusBar->showMessage(stdWToQString(message.c_str()));
				ShowContext(true);
			}
		}
	}
}
void ConexMain::RemoveAnyFromContext() {
	if(_currentTerm) {

	}
}

void ConexMain::ShowContext(bool isTermEdit) {
	if(isTermEdit) {
		ui.addAuthorButton->hide();
		ui.authorGroup->hide();
		ui.addNamespacesButton->hide();
		ui.namespaceGroup->hide();		
		ui.addSimilarButton->show();
		ui.similarGroup->show();
		ui.addHypernymButton->show();
		ui.hypernymGroup->show();
		ui.addClassifierButton->show();
		ui.classifierGroup->show();
		ui.addAntonymButton->show();
		ui.antonymGroup->show();
		if(_currentTerm) {
			//synonyms
			vector<conex::Term*> synonyms;
			_termControl->GetRelationTerms(_currentTerm, conex::SYNONYM, synonyms);
			SAFE_DELETE(_synonymmodel);
			_synonymmodel = new conex::VocabularyTableModel(this);
			_synonymmodel->LoadData(synonyms);			
			ui.synonymsView->setModel(_synonymmodel);
			ui.synonymsView->resizeColumnsToContents();
			//similars
			vector<conex::Term*> similars;
			_termControl->GetRelationTerms(_currentTerm, conex::SIMINYM, synonyms);
			SAFE_DELETE(_similarmodel);
			_similarmodel = new conex::VocabularyTableModel(this);
			_similarmodel->LoadData(similars);
			ui.similarView->setModel(_similarmodel);
			ui.similarView->resizeColumnsToContents();
			//hypernym
			vector<conex::Term*> hypernyms;
			_termControl->GetRelationTerms(_currentTerm, conex::HYPERNYM, synonyms);
			SAFE_DELETE(_hypernymmodel);
			_hypernymmodel = new conex::VocabularyTableModel(this);
			_hypernymmodel->LoadData(hypernyms);
			ui.hypernymView->setModel(_hypernymmodel);
			ui.hypernymView->resizeColumnsToContents();
			//classifier
			vector<conex::Term*> classifiers;
			_termControl->GetRelationTerms(_currentTerm, conex::CATEGORY, synonyms);
			SAFE_DELETE(_classifiermodel);
			_classifiermodel = new conex::VocabularyTableModel(this);
			_classifiermodel->LoadData(classifiers);
			ui.classifierView->setModel(_classifiermodel);
			ui.classifierView->resizeColumnsToContents();
			//antonym
			vector<conex::Term*> antonyms;
			_termControl->GetRelationTerms(_currentTerm, conex::ANTONYM, synonyms);
			SAFE_DELETE(_antonymmodel);
			_antonymmodel = new conex::VocabularyTableModel(this);
			_antonymmodel->LoadData(antonyms);
			ui.antonymView->setModel(_antonymmodel);
			ui.antonymView->resizeColumnsToContents();
			//show them
			ui.termTab->setCurrentIndex(1);
		}
	}else {
		ui.addAuthorButton->show();
		ui.authorGroup->hide();
		ui.addNamespacesButton->show();
		ui.namespaceGroup->show();
		ui.addSimilarButton->hide();
		ui.similarGroup->hide();
		ui.addHypernymButton->hide();
		ui.hypernymGroup->hide();
		ui.addClassifierButton->hide();
		ui.classifierGroup->hide();
		ui.addAntonymButton->hide();
		ui.antonymGroup->hide();
		if(_voc) {
			//synonyms
			//conex::VocabularyContext* context = _voc->GetVocabularyContext();
			vector<conex::Term*> synonyms;
			//context->GetSynonyms(synonyms);
			SAFE_DELETE(_synonymmodel);
			_synonymmodel = new conex::VocabularyTableModel(this);
			_synonymmodel->LoadData(synonyms);
			ui.synonymsView->setModel(_synonymmodel);
			ui.synonymsView->resizeColumnsToContents();
			//author
			vector<conex::Term*> authors;
			//context->GetAuthor(authors);
			SAFE_DELETE(_authormodel);
			_authormodel = new conex::VocabularyTableModel(this);
			_authormodel->LoadData(authors);
			ui.authorView->setModel(_authormodel);
			ui.authorView->resizeColumnsToContents();
			//hypernym
			vector<conex::Term*> namespaces;
			//context->GetNamespace(namespaces);
			SAFE_DELETE(_namespacemodel);
			_namespacemodel = new conex::VocabularyTableModel(this);
			_namespacemodel->LoadData(namespaces);
			ui.namespaceView->setModel(_namespacemodel);
			ui.namespaceView->resizeColumnsToContents();
			//show them
			ui.termTab->setCurrentIndex(1);
		}
	}
	ui.removeButton->hide();
}

/*! Convert a QString to an std::wstring */
std::wstring ConexMain::qToStdWString(const QString &str)
{
#ifdef _MSC_VER
	return std::wstring((const wchar_t *)str.utf16());
#else
	return str.toStdWString();
#endif
}

/*! Convert an std::wstring to a QString */
QString ConexMain::stdWToQString(const std::wstring &str)
{
#ifdef _MSC_VER
	return QString::fromUtf16((const ushort *)str.c_str());
#else
	return QString::fromStdWString(str);
#endif
}


